const express = require('express');
const admin = express.Router();
const bcrypt = require('bcryptjs')
// token
const jwt = require('jsonwebtoken');
// 验证Token
const passport = require('passport')
const svgCaptcha = require('svg-captcha');
const axios = require('axios')
const CryptoJS = require('crypto-js')
const forge = require('node-forge')
const OpenAI = require('openai')
const db = require('../config/mysqlConfig')
const transporter = require('../config/nodemailerConfig')
const validateFields = require('../middleware/validator')
const { generatePassword } = require('../util/tool')
const multer = require('multer')
const pdf = require('pdf-parse');
const fs = require('fs');
const storage = multer.diskStorage({
  // 指定文件存储目录
  destination: (req, file, cb) => {
    cb(null, 'uploads/'); // 文件保存到 uploads/ 目录
  },

  // 自定义文件名（避免重名）
  filename: (req, file, cb) => {
    // 原始文件名
    const decodedName = Buffer.from(file.originalname, 'latin1').toString('utf8');
    const finalName = `${decodedName}`;
    cb(null, finalName);
  }
});
const upload = multer({
    storage,
    fileFilter: (req, file, cb) => {
        if (!(file.mimetype == 'application/pdf')) {
            const error = new Error('文件类型不正确');
            // error.code = 'LIMIT_FILE_TYPE';
            cb(error, false);
        } else {
            cb(null, true);
        }
    },
    limits: {
        fileSize: 1 * 1024 * 1024, // 限制 5MB
    },
});

const salt = bcrypt.genSaltSync(10);
const keys = 'aiProject'

// 生成RSA密钥对
const keypair = forge.pki.rsa.generateKeyPair({ bits: 2048, e: 0x10001 });
const publicKey = forge.pki.publicKeyToPem(keypair.publicKey);
const privateKey = forge.pki.privateKeyToPem(keypair.privateKey);

const decryptData = (encryptedData) => {
    try{
        const { pki, util } = forge;
        const privateKeyObj = pki.privateKeyFromPem(privateKey);
        const decodedData = forge.util.decode64(encryptedData);
        const decryptedData = privateKeyObj.decrypt(decodedData, 'RSA-OAEP');
        return util.decodeUtf8(decryptedData);
    } catch (err) {
        return ''
    }
};

admin.get('/publicKey', (req, res) => {
    res.json({ code: 0, msg: '成功', key: publicKey});
})

const sendMail = async (user, email, res) => {
    const numbers = generatePassword()
    const mailOptions = {
        from: '"未来智匠" <835150891@qq.com>', 
        to: email, 
        subject: "冒险者请查看您的通行密令", 
        html: `<h3>您的通行密令为：${numbers}，期待您的冒险之旅</h3>`
    }
    const info = await transporter.sendMail(mailOptions);
    db.query('update users set password = ? where username = ?', [bcrypt.hashSync(numbers, salt), user], (err, results) => {
        if(err)return res.json({code: 4, msg: err})
        return res.json({
            code: 0,
            msg: '密码重置成功，请前往邮箱查看'
        })
    })
}

// 修改密码
admin.post('/changePassword', (req, res) => {
    const {user, password, newPassword} = req.body;
    const decryptUser = decryptData(user)
    const decryptPassword = decryptData(password)
    const decryptNewPassword = decryptData(newPassword)
    db.query('select * from users where username = ? ', [decryptUser], (err, results) => {
        if(err)return res.json({code: 4, msg: err})
        if (results.length > 0) {
            const isMatch = bcrypt.compareSync(decryptPassword, results[0].password);
            if (isMatch) {
                db.query('update users set password = ? where username = ?', [bcrypt.hashSync(decryptNewPassword, salt), decryptUser], (error, result) => {
                    if(error)return res.json({code: 4, msg: error})
                    return res.json({
                        code: 0,
                        msg: '密码修改成功'
                    })
                })
            } else {
                res.json({
                    code: 2,
                    msg: '密码错误'
                })
            }
        } else {
            res.json({
                code: 1,
                msg: '账号不存在'
            })
        }
    })
})

// 重置密码邮件
admin.post('/resetPassword', (req, res) => {
    const { user, email } = req.body
    db.query('select * from users where username = ?', [user], (err, results) => {
        if (results.length > 0) {
            sendMail(user, email, res)
        } else {
            res.json({
                code: 1,
                msg: '账号不存在'
            })
        }
    })
})

// deepseek大模型
// let context = [];
admin.post('/deepseekMoudle', (req, res) => {
    const { text, moduleId } = req.body
    const openai = new OpenAI({
        baseURL: 'https://api.deepseek.com',
        apiKey: process.env.DEEPSEEK_APIKEY
    });
    async function streamChatCompletion() {
        try {
            let reasoning_content = ""
            let response = "";
            // context.push({ role: "user", content: text });
            const gptStream = await openai.chat.completions.create({
                messages: text,
                model: moduleId,
                stream: true // stream
            });
    
            res.writeHead(200, { 'Content-Type': 'text/event-stream' }) // 'text/event-stream' 标识 SSE 即 Server-Sent Events
            for await (const chunk of gptStream) {
                if (chunk.choices && chunk.choices[0].delta.reasoning_content) {
                    reasoning_content += chunk.choices[0].delta.reasoning_content
                }
                if (chunk.choices && chunk.choices[0].delta.content) {
                    response += chunk.choices[0].delta.content
                }
                res.write(`data: ${JSON.stringify(chunk)}\n\n`) // 注意，格式必须是 `data: xxx\n\n` ！！！
            }
            // context.push({ role: "assistant", content: response });
        } catch (error) {
            if (error.status == 402) {
                res.writeHead(200, { 'Content-Type': 'text/event-stream' })
                res.write(`data: ${JSON.stringify({message: "账户余额不足"})}\n\n`)
            } else if (error.status == 400) {
                // context = [];
            }
        }
        res.end();
    }
    streamChatCompletion();
})

// 验证token是否过期和正确
const authenticateToken = (req, res, next) => {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];
    jwt.verify(token, keys, (err, user) => {
        if (err) return res.status(200).json({ code: 6, msg: 'token无效或已过期，请重新登录' });
        req.user = user;
        next();
    });
}
const generateAppId = () => {
    // 生成一个随机的UUID v4格式的ID
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      const r = Math.random() * 16 | 0;
      const v = c === 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
}

// 修改个人头像和昵称
admin.post('/updateUser', [authenticateToken, validateFields(['nickname', 'img_url', 'username'])], (req, res) => {
    const { nickname, img_url, username } = req.body;
    db.query('update users set nickname = ?, img_url = ? where username = ?', [nickname, img_url, username], (error, results) => {
        if (error) {
            return res.json({code: 4,msg: error})
        }
        res.json({
            code: 0,
            msg: '保存成功'
        })
    })
})

// 用户注册
admin.post('/register', (req, res) => {
    let { name, user, email, password, img_url, captcha } = req.body;
    let massage = ''
    const ip = req.headers['x-forwarded-for'] || req.ip || req.socket.remoteAddress;
    if (/[\u4e00-\u9fa5]/g.test(user) || /[\u4e00-\u9fa5]/g.test(password)) {
        massage = '冒险者ID或通行密令不能使用中文'
        return res.json({code: 4,msg: massage})
    }
    db.query('select * from users where ip = ?',[ip], (err1, results1) => {
        if(err1) return res.json({code: 4, msg: err1})
        if (results1.length > 0) {
            return res.json({
                code: 2,
                msg: '该ip地址已注册过一个账号'
            })
        } else {
            db.query('select * from users where username = ?',[user], (err2, results2) => {
                if (err2) {
                    return res.json({code: 4, msg: err2})
                }
                if (results2.length > 0) {
                    res.json({
                        code: 1,
                        msg: '账号已存在'
                    })
                } else {
                    db.query('select * from users where email = ?', [email], (err4, results4) => {
                        if(err4) return res.json({code: 4, msg: err4})
                        if (results4.length > 0) {
                            res.json({
                                code: 1,
                                msg: '邮箱已存在'
                            })
                        } else {
                            if (req.session.captcha == captcha.toLowerCase()) {
                                db.query('insert into users (username, password, nickname, email, img_url, ip, appid) values (?, ?, ?, ?, ?, ?, ?)',[user, bcrypt.hashSync(password, salt), name, email, img_url, ip, generateAppId()], (err3, results3) => {
                                    req.session.destroy()
                                    if (err3) {
                                        res.json({
                                            code: 4,
                                            msg: err3
                                        })
                                    } else {
                                        res.json({
                                            code: 0,
                                            msg: '注册成功'
                                        })
                                    }
                                })
                            } else {
                                res.json({
                                    code: 3,
                                    msg: '验证码错误'
                                })
                            }
                        }
                    })
                }
            });
        }
    })
})

// 用户登录
admin.post('/login', validateFields(['user', 'password']), (req, res) => {
    const { user, password } = req.body;
    const decryptUser = decryptData(user)
    const decryptPassword = decryptData(password)
    if (!decryptUser) {
        return res.json({code: 4, msg: '账号解密失败'})
    }
    db.query('select * from users where binary username = ? or email = ?',[decryptUser, decryptUser], (err, results) => {
        if (err) {
            return res.json({code: 4,msg: err})
        }
        if (results.length > 0) {
            if (!decryptPassword) {
                return res.json({code: 4, msg: '密码解密失败'})
            }
            const isMatch = bcrypt.compareSync(decryptPassword, results[0].password);
            if (isMatch) {
                const rules={id: results[0].id, name: results[0].username}
                jwt.sign(rules,keys,{expiresIn:'1h'},(tokenErr,token)=>{
                    if (tokenErr) {
                        return res.json({code: 5,msg: 'token生成不对'})
                    }
                    res.json({
                        code: 0,
                        msg: '登录成功',
                        token: "Bearer " + token
                    })
                })
            } else {
                res.json({
                    code: 2,
                    msg: '密码错误'
                })
            }
        } else {
            res.json({
                code: 1,
                msg: '账号或者邮箱不存在'
            })
        }
    });
})

// 获取用户信息
admin.get('/getUser', authenticateToken, (req, res) => {
    if (req.user) {
        db.query('select * from users where username = ? AND id = ?',[req.user.name, req.user.id], (err, results) => {
            if (err) {
                return res.json({code: 4,msg: err})
            }
            res.json({
                code: 0,
                msg: '成功',
                users: {
                    id: results[0].id,
                    nickname: results[0].nickname,
                    username: results[0].username,
                    img_url: results[0].img_url,
                    appid: results[0].appid,
                }
            })
        })
    } else {
        res.json({
            code: 4,
            msg:'非法Token'
        })
    }
})

// 添加大模型分类
admin.post('/addCategory', [authenticateToken, validateFields(['self_introduction', 'my_name', 'name', 'introduce', 'user_id'])], (req, res) => {
    const { self_introduction, my_name, name, introduce, user_id }  = req.body;
    const imgIndex = Math.floor(Math.random() * 6) + 1;
    let category_img = ""
    switch (imgIndex) {
        case 1:
            category_img = "https://s1.imagehub.cc/images/2024/12/23/7049b9735c066e9267ca75ed043b0852.th.png"
            break;
        case 2:
            category_img = "https://s1.imagehub.cc/images/2024/12/23/1645c7845cafece9c8b6cb83306c7b66.th.png"
            break;
        case 3:
            category_img = "https://s1.imagehub.cc/images/2024/12/23/5696a6b0eb9637dfa55fff8bf616bb35.th.png"
            break;
        case 4:
            category_img = "https://s1.imagehub.cc/images/2024/12/23/4c83b1abee9c6631259a95086bac0b9e.th.png"
            break;
        case 5:
            category_img = "https://s1.imagehub.cc/images/2024/12/23/d6b4f1f876bcad914fe6f1b31b2220c7.th.jpeg"
            break;
        default:
            category_img = "https://s1.imagehub.cc/images/2024/12/23/7c50bce03c953e9f031424a1f36d2510.th.jpg"
    }
    db.query('select * from category where my_name = ? and user_id = ?', [my_name, user_id], (fault, consequence) => {
        if (fault) return res.json({code: 4, msg: fault})
        if ( consequence.length > 0) {
            res.status(200).json({
                code: 1,
                msg: '已存在聊天搭子'
            })
        } else {
            const query = 'insert into category (self_introduction, my_name, name, introduce, user_id, category_img) values (?,?,?,?,?,?)'
            db.query(query, [self_introduction, my_name, name, introduce, user_id, category_img], (err, results) => {
                if (err) return res.json({code: 4, msg: err})
                res.status(200).json({
                    code: 0,
                    msg: '添加成功'
                })
            })
        }
    })
})

// 添加客服应用配置项
admin.post('/addCustomerService', authenticateToken, (req, res) => {
    const { appid, welcomeText, signature, title, techBrand, themeColor }  = req.body;
    db.query('select * from customer_service where appid = ?', [appid], (err, result) => {
        if (err) return res.json({code: 4, msg: err})
        if (result.length > 0) {
            db.query('update customer_service set welcomeText = ?, signature = ?, title = ?, techBrand = ?, themeColor = ? where appid = ?',[welcomeText, signature, title, techBrand, themeColor, appid], (err1, result1) => {
                if (err1) return res.json({code: 4, msg: err1})
                res.status(200).json({
                    code: 0,
                    msg: '客服配置更新成功'
                })
            })
        } else {
            const query = 'insert into customer_service (appid, welcomeText, signature, title, techBrand, themeColor) values (?,?,?,?,?,?)'
            db.query(query, [appid, welcomeText, signature, title, techBrand, themeColor], (err2, result2) => {
                if (err2) return res.json({code: 4, msg: err2})
                res.status(200).json({
                    code: 0,
                    msg: '客服配置保存成功'
                })
            })
        }
    })
})

// 查询客服应用配置项
admin.get('/queryCustomerService', (req, res) => {
    const { appid } = req.query
    db.query('select * from customer_service where appid = ?', [appid], (err, results) => {
        if (err) return res.json({code: 4, msg: err})
        if (results.length > 0) {
            res.status(200).json({
                code: 0,
                msg: '成功',
                data: results[0]
            })
        } else {
            res.status(200).json({
                code: 1,
                msg: '查询失败'
            })
        }
    })
})

// 添加对话信息（优化）
admin.post('/addDialogue', authenticateToken, (req, res) => {
    const dialogue  = req.body;
    const values = dialogue.map(item => [item.myself_reply, item.ai_reply, item.category_id, item.user_id]);
    const query = 'insert into dialogue ( myself_reply, ai_reply, category_id, user_id) values ?'
    db.query(query, [values], (err, results) => {
        if (err) return res.json({code: 4, msg: err})
        res.status(200).json({
            code: 0,
            data: '添加成功'
        })
    })
})

// 查询用户下的大模型分类
admin.get('/queryCategory', authenticateToken, (req, res) => {
    const { user_id }  = req.query
    const query = 'select * from category where user_id = ?'
    db.query(query, [user_id], (err, results) => {
        if(err)return res.json({code: 4, msg: err})
        res.status(200).json({
            code: 0,
            msg: '成功',
            data: results
        })
    })
})

// 查询大模型分类下的对话内容
admin.get('/queryDialogue', authenticateToken, (req, res) => {
    const { category_id }  = req.query
    const query = 'select * from dialogue where category_id = ?'
    db.query(query, [category_id], (err, results) => {
        if(err)return res.json({code: 4, msg: err})
            let a1 = []
            for (let i=0;i<results.length;i++) {
                let b1 = {
                    userText: results[i].myself_reply,
                    adminContent: {
                        adminText: results[i].ai_reply,
                        isShow: false
                    },
                    quote: results[i].quote
                }
                a1.push(b1)
            }
        res.status(200).json({
            code: 0,
            msg: '成功',
            data: a1
        })
    })
})

// 删除大模型分类
admin.post('/deleteCategory', [authenticateToken, validateFields(['category_id'])], (req, res) => {
    const { category_id } = req.body
    const query = 'delete from category where category_id = ?'
    db.query(query, [category_id], (err, results) => {
        if(err)return res.json({code: 4, msg: err})
        res.status(200).json({
            code: 0,
            msg: "删除成功"
        })
    })
})

// 删除大模型分类下的内容
admin.post('/deleteDialogue', [authenticateToken, validateFields(['category_id', 'user_id'])], (req, res) => {
    const { category_id, user_id } = req.body
    if (!category_id) {
        return res.status(200).json({
                    code: 1,
                    msg: "大模型类别id不能为空"
                })
    }
    const query = 'delete from dialogue where category_id = ? and user_id = ?'
    db.query(query, [category_id, user_id], (err, results) => {
        if(err)return res.json({code: 4, msg: err})
        res.status(200).json({
            code: 0,
            msg: "已清空历史记录"
        })
    })
})

// 查询模板大类
admin.get('/queryPrompt', authenticateToken, (req, res) => {
    const query = 'select * from tag'
    db.query(query, (err, results) => {
        if(err)return res.json({code: 4, msg: err})
        res.status(200).json({
            code: 0,
            msg: '成功',
            data: results
        })
    })
})

// 查询模板信息（包含分页功能）
admin.get('/queryTemplate', authenticateToken, (req, res) => {
    const { template_id } = req.query
    const page = parseInt(req.query.page)
    const pageSize = parseInt(req.query.pageSize)
    const offset = parseInt(page - 1) * pageSize
    const query = 'select * from text_template where template_id = ? limit ? offset ?'
    db.query(query, [template_id, pageSize, offset], (err, results) => {
        if(err)return res.json({code: 4, msg: err})
            const allCount = 'select count(*) as count from text_template where template_id = ?'
            db.query(allCount, [template_id], (err, total) => {
                if (err)return res.json({code: 4, msg: err})
                res.status(200).json({
                    code: 0,
                    msg: '成功',
                    data: {
                        page: page,
                        pageSize: pageSize,
                        total: total[0].count,
                        data: results
                    }
                })
            })
    })
})

// 验证码生成
admin.get('/captcha', (req, res) => {
    const captcha = svgCaptcha.create({
        size: 6, // 验证码长度
        ignoreChars: '0o1i', // 忽略容易混淆的字符
        noise: 2, // 干扰线条的数量
        color: true, // 是否有颜色
        background: '#cc9966' // 背景颜色
    });
    req.session.captcha = captcha.text.toLowerCase()
    // res.type('svg'); // 生成img格式
    res.status(200).json({
        code: 0,
        imgData: captcha.data
    });
});

// 图片生成
admin.post('/queryImg', [authenticateToken, validateFields(['prompt'])], (req, res) => {
    const { prompt } = req.body
    const XUNFEI_CONFIG = {
        APPID: 'f4261d9b', // Your Xunfei AppID
        API_SECRET: 'MDhmODBmZTliZDBjYmFjYmU3NmZlN2My', // Your Xunfei API Secret
        API_KEY: '3e31765e9bd687b76544458a51f76e9a', // Your Xunfei API Key
        API_URL: 'https://spark-api.cn-huabei-1.xf-yun.com/v2.1/tti', // Xunfei Spark Image API URL
    }
    const host = 'spark-api.xf-yun.com';
    const date = new Date().toUTCString();
    const algorithm = 'hmac-sha256';
    const headers = 'host date request-line';
    const requestLine = 'POST /v2.1/tti HTTP/1.1';
    const signature_origin = `host: ${host}\ndate: ${date}\n${requestLine}`;
    
    const signature = CryptoJS.HmacSHA256(signature_origin, XUNFEI_CONFIG.API_SECRET);
    const sign = CryptoJS.enc.Base64.stringify(signature);
    
    const authorization_origin = `api_key="${XUNFEI_CONFIG.API_KEY}", algorithm="${algorithm}", headers="${headers}", signature="${sign}"`;
    const authorization = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(authorization_origin));
    
    const url = `${XUNFEI_CONFIG.API_URL}?authorization=${authorization}&date=${encodeURI(date)}&host=${host}`;
    const requestBody = {
        header: {
            app_id: XUNFEI_CONFIG.APPID,
        },
        parameter: {
            chat: {
                domain: "general",
                width: 640,
                height: 640
            }
        },
        payload: {
            message: {
                text: [
                    {
                    role: "user",
                    content: prompt
                    }
                ]
            }
        }
    };
    
    const config = {
        method: 'post',
        url: url,
        headers: { 
           'Content-Type': 'application/json'
        },
        data : requestBody
    };
     
    axios(config)
        .then(function (response) {
            res.status(200).json({
                code: 0,
                msg: '成功',
                imglist: response.data
            })
        })
        .catch(function (error) {
            res.json({
                code: 4,
                msg: error
            })
        });
})

// 上传文件
admin.post('/uploadFile', upload.single('avatar'), async (req, res) => {
    // 读取上传的PDF文件
    const dataBuffer = fs.readFileSync(req.file.path);
    
    // 解析PDF
    const pdfData = await pdf(dataBuffer);
    
    // 删除临时文件（可选）
    // fs.unlinkSync(req.file.path);

    const imageUrl = `${req.protocol}://${req.get('host')}/uploads/${req.file.filename}`;

    // 返回解析结果
    return res.json({
                code: 0,
                msg: '文件上传成功',
                data: {
                    originalName: req.file.filename,
                    text: pdfData.text,
                    metadata: pdfData.metadata,
                    numPages: pdfData.numpages,
                    url: imageUrl
                }
            });
});

// 处理整体错误
admin.use((err, req, res, next) => {
  if (err instanceof multer.MulterError) {
    // Multer特有的错误
    if (err.code === 'LIMIT_FILE_SIZE') {
      return res.status(200).json({
        code: 1,
        msg: '文件大小超过限制(最大1MB)',
        maxSize: '1MB'
      });
    }
    return res.status(200).json({
      code: 1,
      msg: '文件上传错误: ' + err.message
    });
  } else if (err) {
    // 其他类型的错误
    return res.status(200).json({
      code: 1,
      msg: '服务器错误: ' + err.message
    });
  }
  next();
});

module.exports = admin;